package com.atjinggu.jinggumail.product.web;

import com.atjinggu.jinggumail.common.constant.AuthConstant;
import com.atjinggu.jinggumail.product.entity.CategoryEntity;
import com.atjinggu.jinggumail.product.service.CategoryService;
import com.atjinggu.jinggumail.product.vo.CateLog2Vo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author jingming
 * @Type IndexController.java
 * @Desc
 * @date 2021/1/11 15:14
 */
@Controller
public class IndexController {

    @Autowired
    CategoryService categoryService;

    @Autowired
    RedissonClient redisson;


    @Autowired
    StringRedisTemplate redisTemplate;

    @GetMapping({"/index.html","/"})
    public String indexPage(Model model, HttpServletRequest request){
        //查询出所有的一级分类
     List<CategoryEntity> list =   categoryService.getLevel1Categorys();
        String level1 = redisTemplate.opsForValue().get("level1");
        System.out.println(level1);
        model.addAttribute("categorys",list);

request.getSession().getAttribute(AuthConstant.LOGIN_USER);
       //前缀默认：classpath:/templates/
       // 后缀默认：.html
        return "index";
    }

    @ResponseBody
    @GetMapping("/index/categoryTree")
    public Map<String, List<CateLog2Vo>> getCategoryTree(){
        Map<String, List<CateLog2Vo>> map =  categoryService.getCategoryTree();
        return map;

    }

    @ResponseBody
    @GetMapping("/hello")
    public String hello(){
        RLock lock = redisson.getLock("my-lock");
        lock.lock(); //阻塞式锁，默认等待时间为30s
        lock.lock(35,TimeUnit.SECONDS); //手动指定超时时间
        try {
            //1.锁的自动续期，如果业务超长，运行期间自动给锁续上新的30s，不用担心业务时间过长，锁自动过期被删掉
            //2.加锁的业务只要完成，就不会给当前锁续期，即时不手动解锁，锁默认在30s以后自动删除
            System.out.println("开始执行业务 " + Thread.currentThread().getId());
            try {
                TimeUnit.SECONDS.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }finally {
            lock.unlock();
        }
        return "hello";
    }


    //包证一定能读到最新的数据，修改期间，写锁是一个排他锁（互斥锁），读锁是一个共享锁
    //写锁没释放，读锁就必须等待
    //读 + 读 =》 相当于无锁，只会在redis中记录好读锁，他们都会加锁成功
    //写 + 读 =》 等待写锁释放
    //写 + 写 =》 阻塞，等待前一个释放
    //读 + 写 =》 有读锁，写锁也需要等待
    //总结：只要有写锁在，就需要等待
    @ResponseBody
    @GetMapping("/read")
    public String read(){
        RReadWriteLock lock = redisson.getReadWriteLock("read-write");
        RLock rLock = lock.readLock();
        String s = "";
        try {
            rLock.lock();
            System.out.println("获取到");
             s = redisTemplate.opsForValue().get("write-value");
            TimeUnit.SECONDS.sleep(15);
        }catch (Exception e){

        }finally {
            rLock.unlock();
        }
        return s;
    }

    @ResponseBody
    @GetMapping("/write")
    public String write(){
        RReadWriteLock lock = redisson.getReadWriteLock("read-write");
        RLock rLock = lock.writeLock();
        rLock.lock();
        String uuid = UUID.randomUUID().toString();
        try {
            TimeUnit.SECONDS.sleep(20);
            redisTemplate.opsForValue().set("write-value", uuid);
        }catch (Exception e){

        }finally {
           rLock.unlock();
        }
      return uuid;
    }


    @ResponseBody
    @GetMapping("/park")
    public String park() throws InterruptedException {
        RSemaphore semphore = redisson.getSemaphore("park");
        semphore.acquire();  //获取信号量，阻塞操作
       // boolean b = semphore.tryAcquire();
        return "park ok";
    }

    @ResponseBody
    @GetMapping("/go")
    public String go(){
        RSemaphore semphore = redisson.getSemaphore("park");
        semphore.release();  //获取信号量，阻塞操作
        return "go ok";
    }

    @ResponseBody
    @GetMapping("/lock")
    public String lock() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("count-latch");
        countDownLatch.trySetCount(5);
        countDownLatch.await();
        return "lock ok";
    }

    @ResponseBody
    @GetMapping("/leave")
    public String leave() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("count-latch");
        countDownLatch.countDown();
        return "leave ok";
    }
}